package com.neusoft.yiyang.auth.security;

import io.jsonwebtoken.*;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

@Slf4j
@Component
public class JwtTokenProvider {

    @Value("${spring.security.jwt.secret}")
    private String secretKey;

    @Value("${spring.security.jwt.expiration}")
    private long expiration;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostConstruct
    public void init() {
        log.info("JWT配置加载成功 - secret: {}, expiration: {}秒",
                secretKey != null ? "[已加载]" : "[未加载]", expiration);
    }

    /**
     * 生成 JWT Token
     * @param claims Token 中封装的用户信息
     * @param subject 用户名
     * @return 生成的 Token
     */
    public String generateToken(Map<String, Object> claims, String subject) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration * 1000);

        return Jwts.builder()
                .setClaims(claims)  // 设置额外的 claims 信息
                .setSubject(subject)  // 设置用户的主标识（用户名）
                .setIssuedAt(now)  // 设置签发时间
                .setExpiration(expiryDate)  // 设置过期时间
                .signWith(SignatureAlgorithm.HS256, secretKey)  // 使用 HS256 签名算法，密钥为 secretKey
                .compact();  // 创建 Token
    }

    /**
     * 验证 JWT Token 是否有效
     * @param token JWT Token
     * @return 是否有效
     */
    public boolean validateToken(String token) {
        try {
            // 1. 检查Redis黑名单
            Boolean isBlacklisted = redisTemplate.hasKey("jwt:blacklist:" + token);
            if (Boolean.TRUE.equals(isBlacklisted)) {
                log.warn("Token在黑名单中: {}", token);
                return false;
            }

            // 2. 验证JWT本身（签名、过期时间等）
            Claims claims = parseClaims(token);

            // 3. 额外验证：检查Token是否提前过期（如用户权限变更导致的强制失效）
            // 这里可以添加自定义逻辑，例如从Redis获取用户权限状态

            return true;
        } catch (ExpiredJwtException e) {
            log.warn("Token已过期: {}", e.getMessage());
            return false;
        } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) {
            log.warn("无效的JWT: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 从 JWT Token 中解析 Claims
     * @param token JWT Token
     * @return Claims
     */
    private Claims parseClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从 JWT Token 中提取额外的信息
     * @param token JWT Token
     * @return 提取的信息
     */
    public long getTokenRemainingTime(String token) {
        try {
            Claims claims = parseClaims(token);
            Date expirationDate = claims.getExpiration();
            return expirationDate.getTime() - System.currentTimeMillis();
        } catch (Exception e) {
            return 0;
        }
    }
}
